use std::net::SocketAddr;
use rbatis::logic_delete::RbatisLogicDeletePlugin;
use time::macros::format_description;
use time::UtcOffset;
use tracing_error::ErrorLayer;
use tracing_subscriber::{EnvFilter, fmt, layer::SubscriberExt, Registry, util::SubscriberInitExt};
use tracing_subscriber::fmt::time::OffsetTime;

mod utils;

use config::CONFIG;
use utils::app;
use utils::signals;
use cores::db::RB;
use cores::logger::{LogConfig, non_blocking};

#[tokio::main]
async fn main() {
    println!("Run Debug Mode: {}", CONFIG.read().await.debug());
    // 设置日志
    let log_config: LogConfig = CONFIG.read().await.log_config().clone();

    let time_offset = UtcOffset::from_hms(8, 0, 0).unwrap();

    let env_filter = EnvFilter::new(
        std::env::var("RUST_LOG").unwrap_or_else(|_| log_config.level().to_owned()),
    );

    let local_time = OffsetTime::new(
        time_offset,
        format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:3]"),
    );

    // 输出到控制台中
    let console_layer = fmt::layer()
        .pretty()
        .with_timer(local_time.clone())
        .with_writer(std::io::stderr);

    // 输出到文件中
    let file_appender = cores::logger::minutely(time_offset, log_config.path(), log_config.file_name());
    let (non_blocking_appender, _guard) = non_blocking(file_appender);
    let file_layer = fmt::layer()
        .with_ansi(false)
        .with_timer(local_time)
        .with_writer(non_blocking_appender);

    Registry::default()
        .with(env_filter)
        .with(ErrorLayer::default())
        .with(console_layer)
        .with(file_layer)
        .init();

    // 安裝 color-eyre 的 panic 处理句柄
    color_eyre::install().unwrap();

    let plugin = RbatisLogicDeletePlugin::new("delete_flag");
    RB.write().await.set_logic_plugin(plugin);
    RB.read().await.link(CONFIG.read().await.database_url()).await.unwrap();
    // RB.read().await.link("mysql://root:123456@localhost:3306/auth_test").await.unwrap();

    // run it
    let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
    tracing::info!("listening on {}", addr);
    axum::Server::bind(&addr)
        .serve(app::app().await.into_make_service())
        .with_graceful_shutdown(signals::shutdown_signal())
        .await
        .unwrap();
}
